package com.myway.service.ibe.command;

import com.alibaba.fastjson.JSON;
import com.myway.dto.domain.IBEPnr;
import com.myway.dto.domain.IBESegment;
import com.myway.dto.domain.Segment;
import com.myway.dto.vo.FlySegmentVo;
import com.myway.service.ibe.PNRCommandService;
import com.myway.utils.DateUtils;
import com.travelsky.ibe.client.pnr.*;
import com.travelsky.ibe.exceptions.DETRNonETPNRException;
import com.travelsky.ibe.exceptions.IBEException;
import com.travelsky.ibe.exceptions.RTNoPNRException;
import com.travelsky.ibe.exceptions.RTPNRCancelledException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * Created by Administrator on 2018/8/3.
 */
@Slf4j
public class PNRCommand extends  BaseIBECommand implements PNRCommandService{

    public String cancelPnr(String pnrNo){
        try {
            PnrManage p = new PnrManage();
            this.configIBEClient(p);
            String result=p.deletePnr(pnrNo);
            return result;
        }catch (Exception e ){
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据PNR码获取PNR信息
     * @param pnrNo
     * @return
     */
    public String getPnrByPnrNo(String pnrNo) throws Exception{
        RT rt = new RT();
        this.configIBEClient(rt);
        RTResult rtResult=new RTResult();
        try {
            int tryNumber = 0;
            while (tryNumber < 3) {
                try {
                    rtResult=rt.retrieve(pnrNo);
                    break;
                } catch (com.travelsky.ibe.exceptions.IBEException e) {
                    if(e.getMessage().contains("connect")||e.getMessage().contains("timed out")){//只有连接异常重试
                        tryNumber++;
                        log.error("getPnrByPnrNo IBE error("+pnrNo+") 重试:"+tryNumber,e);
                        if(tryNumber==3)throw new IBEException(e);
                    }else{
                        throw new IBEException(e);
                    }
                }catch (Exception e) {
                    log.error("getPnrByPnrNo unkown error:"+pnrNo,e);
                    throw new IBEException(e);
                }
            }
        } catch (Exception e) {
            log.error("PNR信息获取失败,异常信息："+e.getMessage());
            throw new IBEException(e);
        }
        return JSON.toJSONString(rtResult);
    }

    /**
     * @名称：isPnrAvailable
     * @描述：PNR是否可用
     * 没有取消或不存在
     * @param pnrNo
     * @return
     */
    public boolean isPnrAvailable(String pnrNo) throws Exception{
        boolean b=true;
        try {
            getPnrByPnrNo(pnrNo);
        } catch (Exception e) {
            if(e.getMessage().contains("RTPNRCancelledException")||e.getMessage().contains("RTNoPNRException")){
                b=false;
            }else{
                throw new IBEException(e);
            }
        }
        return b;
    }
    /**
     * @名称：reconfirm
     * @描述：RR PNR中的所有航段
     * @param pnrNo
     * @param segments
     */
    public void reconfirm(String pnrNo, List<FlySegmentVo> segments) throws Exception {
        PnrManage pnrMgr = new PnrManage();
        this.configIBEClient(pnrMgr);
        try {
            if (checkSegment(pnrNo, segments)) {
                log.debug("Issue command to reconfirm PNR " + pnrNo);
                String result = "OK";
                int tryNumber = 0;
                while (tryNumber < 3) {
                    try {
                        //[IBE] PNR中RR所有航段 生产解开
                        result=pnrMgr.reconfirmAirSeg(pnrNo,
                                null, /* Set null to reconfirm all segments for the given PNR */
                                PnrManage.RECONFIRM_ALL_POSSIBLE_ACTION);
                        break;
                    }  catch (com.travelsky.ibe.exceptions.IBEException e) {
                        if(e.getMessage().contains("connect")||e.getMessage().contains("timed out")){
                            log.error("reconfirm Pnr ibe error:" + pnrNo, e);
                            tryNumber++;
                            if(tryNumber==3)throw new IBEException(e);
                        }else{
                            throw new IBEException(e);
                        }
                    } catch (Exception e) {
                        log.error("reconfirm Pnr unkown error:" + pnrNo, e);
                        throw new IBEException(e);
                    }
                }
                log.debug("Reconfirm result: " + result);

                if (!"OK".equalsIgnoreCase(result)) {
                    throw new IBEException("Reconfirm failed. Result returned from IBE: " + result);
                }
            } else {
                throw new IBEException("Segment in PNR retrieved from IBE is different from expected");
            }
        } catch (Exception e) {
            throw new IBEException("Error during reconfirmation of segment in PNR " + pnrNo + ". " + e.getMessage(), e);
        }
    }
    /**
     * Check whether the segments in <code>TicketIssuanceArtifact</code> match with the actual segments from IBE.
     * @param pnrNo
     * @param segments
     * @return
     */
    private boolean checkSegment(String pnrNo, List<FlySegmentVo> segments) throws Exception {

        // Retrieve segments from IBE based on PNR no and check with segments in issuance object.

        IBEPnr ibePnr = new IBEPnr();
        //FIXME [IBE] 出票、改期升舱出票航段检验 生产环境解开
        ibePnr = retrievePNR(pnrNo);
        log.debug("Total segment(s) retrieved from IBE: " + ibePnr.getSegments().size());

        for (FlySegmentVo seg : segments) {
            boolean found = false;
            for (IBESegment ibeSeg : ibePnr.getSegments()) {
                //缺口程
                if(!StringUtils.hasText(ibeSeg.getActionCode())){
                    continue;
                }
                if (isSameSegment(ibeSeg, seg)) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                throw new IBEException("booking segment " + seg.getFlightNo() + " "
                        + seg.getDepCode() + "-" + seg.getArrCode() + " "
                        + DateUtils.dateToString(seg.getDepTime(), "yyyy-MM-dd HH:mm")
                        + " could not be found in the segments list of IBE");
            }
        }
        log.debug("Segment check OK");
        return true;
    }
    /**
     * @名称：retrievePNR
     * @描述：获取PNR信息
     * retrieve PNR from IBE
     * @param PNR PNR NO
     * @return local IBE result
     */

    @Autowired
    private RetrievePNRCommand retrievePNRCommand;
    public IBEPnr retrievePNR(String PNR){
        Map<String,Object> parms=new HashMap<String,Object>();
        parms.put("PNR", PNR);
        retrievePNRCommand.execute(parms);
        return (IBEPnr)parms.get("IBEPnr");
    }

    private boolean isSameSegment(IBESegment ibeSeg, FlySegmentVo seg) {
        boolean same = false;

        Assert.hasText(ibeSeg.getFlightNo(), "Flight number from IBE is empty");
        Assert.hasText(seg.getFlightNo(), "Flight number is empty");
        Assert.hasText(ibeSeg.getOrgCity(), "Origin city from IBE is empty");
        Assert.hasText(seg.getDepCode(), "Departure port is empty");
        Assert.hasText(ibeSeg.getDesCity(), "Destination city from IBE is empty");
        Assert.hasText(seg.getArrCode(), "Arrival port is empty");

        if (ibeSeg.getFlightNo().trim().equals(seg.getFlightNo().trim())
                && ibeSeg.getOrgCity().trim().equals(seg.getDepCode().trim())
                && ibeSeg.getDesCity().trim().equals(seg.getArrCode().trim())
                && DateUtils.isSameFlightTime(ibeSeg.getDepartureTime(), seg.getDepTime()))
        {

            same = true;
        }

        return same;
    }

    public boolean pnrExist(String pnrNo) throws Exception {
        boolean b=true;
        RT rt = new RT();
        this.configIBEClient(rt);
        try{
            rt.retrieve(pnrNo);
        }catch (RTPNRCancelledException e1){
            b=false;
        }catch (RTNoPNRException e2){
            b=false;
        }catch (Exception e){
            throw new IBEException(e);
        }
        return b;
    }

    public boolean isTicket(String pnrNo){
        boolean b=true;
        DETR de=new DETR();
        this.configIBEClient(de);
        Vector<DETRTKTResult> v = new Vector<DETRTKTResult>();
        try{
            v = de.getTicketInfoByPNR(pnrNo);
        }catch(DETRNonETPNRException e) {
            log.error("Caught DETRNonETPNRException");
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }
        if(!v.isEmpty()) b=false;
        return b;
    }
}
